# Welcome to my home

## Описание
Не находишь, что в последнее время как-то уж больно часто стали ломать наших клиентов, а? Такими темпами, чего доброго, и до нас скоро доберутся. В общем, надо эту тенденцию пресекать на корню! <br>Наши безопасники проанализировали взломы и нашли интересную деталь - у всех взломанных клиентов была установлена эта программа из нашей репошки.<br> Казалось бы, хорошо проверенный и зарекомендовавший себя продукт, безопасность в нём должна быть тоже на уровне... не одни же мы эту штуку используем, верно? <br>Посмотри по-быстрому, что там может быть не так. А то вдруг эти пингвины не умеют читать в документации, как нормально писать конфиги, и им стоит устроить мастер-класс? За отдельные деньги, конечно, ха-ха!

## Hint
Домохозяйкам на заметку - если своим рабочим местом долгое время не заниматься, то там заводятся крысы... Впрочем, это полезно знать не только домохозяйкам, но и админам серверов.


# WriteUp
Файл  представляет собой дистрибутив весьма старого пакета **OpenSSH**, работающего на базе **Cygwin**. <br>Работать с ним рекомендуется в виртуальной машине на базе **Windows XP**.<br>
Но главная особенность этого дистрибутива - вовсе не уязвимости и не недостатки конфигурации. Всё гораздо проще - он просто-напросто пробэкдорен.<br> 
Так как дистрибутив очень старый, большая часть его файлов давно и хорошо известна на том же **VirusTotal**.<br> 
Но один файл выбивается из этой идиллии - **usr\sbin\cygz.dll**. <br>
На первый взгляд может показаться, что он как-то относится к **Cygwin**, но все остальные модули **Cygwin** при этом лежат в папке **bin**. <br>
И более того - среди этих модулей имеется совершенно иной **cygz.dll**. <br>
Это недвусмысленно намекает, что мы имеем дело с техникой **DLL Hijacking** - первым делом сервер **SSH** будет стараться подгружать **DLL** из директории, в которой лежит его исполняемый файл, то есть не оригинальную **DLL** из **Cygwin**, а никому не известный **"новодел"**.

Давайте взглянем на код **usr\sbin\cygz.dll**. Наши догадки подтверждаются - первым делом он выполняет **LoadLibraryA("..\\..\\bin\\cygz")**, получая затем из оригинальной **DLL** адреса функций с теми же именами, которые экспортирует исследуемая **DLL**. 

Изучив её экспорты, несложно понять, для чего это нужно - все вызовы данных **API** будут проксироваться в оригинальную **DLL**.<br> Впрочем, в экспортах больше ничего нет, поэтому посмотрим повнимательнее на происходящее при загрузке нашей **DLL**. 

Как следует покопавшись, можно найти код, который по адресу **0x00406080** делает "**врезку**", совершающую переход на некоторую процедуру **41AF10** внутри исследуемой **DLL**. <br>
Адрес **0x00406080** при работе сервера находится внутри исполняемого файла **sshd.exe**. <br>
Так как исходники открыты, мы можем без особого труда найти соответствующие данному файлу исходные коды и определить, какой именно функции соответствует адрес врезки.<br> 
Эта функция носит название **auth_password** и занимается ни чем иным, как проверкой введенных пользователем кредов.<br> 
Патч располагается точно перед вызовом функции **cygwin_logon_user**, изучим его внимательнее.<br> Выглядит он следующим образом:

```
MOV DWORD PTR SS:[ESP+4],EBX
MOV DWORD PTR SS:[ESP+8],EDI
PUSHAD
PUSH EDI
CALL sub_41ADB0
CMP AL, 0
POPAD
JE @label
MOV EAX, $FFFFFFFF
ADD DWORD PTR [ESP], 0x10
@label:
```

Так, что мы тут видим?<br> 
Первые 2 инструкции - это оригинальные инструкции, которые были затёрты врезкой. 
В них на стеке размещаются аргументы для вызова **cygwin_logon_user**.<br> 
А далее происходит что-то интересное - вызывается процедура, аргументом которой является содержимое **EDI** (а это ни что иное, как **char \*password**), проверяется результат выполнения, и если в нём не **0** - в регистр **EAX** помещается значение **-1**, а содержимое вершины стека увеличивается на **0x10**. <br>
А что у нас там лежит? Ни что иное, как адрес возврата из нашей врезки, то есть в случае, если **sub_41ADB0** вернула **true**, врезка вернет управление не на вызов **cygwin_logon_user**, а куда-то ниже него! <br>
Куда именно?<br> Смотрим в **sshd.exe** и понимаем, что прямиком на вызов **cygwin_set_impersonation_token**. <br>
То есть, если функция **sub_41ADB0** в нашей **DLL** решит, что пароль подходящий, то вся **auth_password** завершится успешно и пользователь получит доступ к серверу!

Отлично, механизм, при помощи которого работает бэкдор, понятен. 

Но что происходит внутри **sub_41ADB0**, какой пароль считается правильным? Разбираемся. 

**Первое**, что мы видим - **пароль** определенно должен быть длиной **больше 4 символов**. 
Эти самые первые **4** его символа вытаскиваются из строки и передаются в функцию **sub_41A93C**, занимающуюся расчетом контрольной суммы. <br>
Понять это можно, посмотрев в вызываемую из **sub_41A93C** функцию **sub_41A918**, в которой происходит **XOR** данных со значениями из массива, расположенного по адресу **dword_41E8A0**. <br>
Этот массив заполняется динамически при запуске программы процедурой **sub_41A968** (её мы получаем, посмотрев перекрестные ссылки для **dword_41E8A0**), и в ней мы видим интересную константу **0xEDB88320**. <br>
Вбиваем её в поиск, и понимаем, что мы имеем дело с "**классикой**" - **CRC32**.

Так, с этим понятно. 

Посчитали **CRC32** **от первых 4 байтов**, что там дальше? 

А вот что:
```
value = 1u % (crc32_result - 0x4F3C4C5F);
```
От значения, возвращенного **CRC32**, вычитается **0x4F3C4C5F**, и затем считается остаток от деления единицы на полученное значение. 

Дальше идёт проверка на то, что этот остаток **равен 0**, и если это так - в функцию **sub_41ABF0** передается указатель на состояющую из первых **4 байтов** пароля строку и указатель **off_41D470**, указывающий на нечто, напоминающее зашифрованные данные. 

Можно предположить, что после этого данные расшифровываются, и по итогу из **sub_41ADB0** возвращается результат сравнения чего-то с ним.

Давайте подумаем, когда выполнится условие 
`1u % (crc32_result - 0x4F3C4C5F) == 0` ? Ответ достаточно очевиден - число **1** даёт в остатке **1** при делении на абсолютно любое число, кроме себя.

Значит, чтобы остаток от деления был нулевым, надо, чтобы **crc32_result** оказался равен **0x4F3C4C60**! 
То есть, первые **4** байта пароля должны иметь **CRC32**, равную **0x4F3C4C60**. <br>
Окей, допустим, мы найдем такую строку - хотя бы путём полного перебора, благо, вариантов не настолько много - и получим ключ для расшифровки. 

Далее, поковырявшись в алгоритме расшифровки, мы поймем, что внутри живет ни что иное, как оборачивающий результаты в **Base64** алгоритм **DES**, возможно даже попытаемся расшифровать данные нашим ключом, получив полный бред... 

И потом, злые и уставшие, мы вдруг осознаем: **нас жёстко кинули**.

Просто потому, что **DES** - это **64-битный блочный шифр**, и результат расшифровки **24 байтной** строки ну никак **не может** оказаться длиной **4 байта**, то есть итоговое сравнение никогда не будет истинным!

Но стоп, а как же тогда работает бэкдор? 

Откатимся немного назад и внимательнее изучим происходящее после расчета **CRC32**. 

А происходит там следующее: бэкдор устанавливает обработчик исключений. <br>Наверно, боится ошибок при расшифровке **DES'a**?<br> 
Ничего подобного: в коде обработчика, который начинается по адресу **0x0041AE75**, нет ничего, связанного с обработкой ошибок, зато накручена куча логики, внутри которой снова фигурирует ссылка на всё ту же зашифрованную строку! 

Вот только она уже никуда не передаётся, а наоборот - сравнивается с результатом выполнения процедуры **sub_41AA5C**. 

Возникает резонный вопрос - а при каком условии мы попадаем в этот обработчик исключений? 

Самый простой и хорошо всем известный способ вызвать исключение - это поделить что-то на **0**, и именно он тут и применяется. 

Для активации блока кода, производящего реальную проверку, необходимо, чтобы **crc32_result** равнялся **0x4F3C4C5F**! <br>
А этому значению соответствует ни что иное, как **4-байтовая строка 'RDG{'**. 

Что ж, похоже, **нас обманули во второй раз**, бэкдор очень даже есть и вполне рабочий. 

Разбираемся теперь с процедурой **sub_41AA5C**. 
Она также внутри реализует алгоритм **DES**, вот только **производит не расшифровку, а зашифровку данных**, используя режим **ECB** и в качестве реального ключа используя **8 первых байтов от SHA1-хеша** того, что ей передают в аргументе. 

Посидев немного, понимаем, что передаваемым в неё для хеширования **ключевым материалом выступит строка, полученная путем двукратного повторения первых 4 байтов введенного пользователем пароля**, то есть **"RDG{RDG{"** (после её хеширования реальным ключом **DES'a** станет **e0 fe 6c ea 00 9c d1 c4**). 

После зашифровки результат переводится в удобную для представления строку при помощи **Base64**. <br>
В качестве данных для зашифровки передается оставшаяся часть пароля (то есть, введенный пользователем пароль с "**отрезанными**" первыми **4** символами). <br><br>
Полученный результат сравнивается со строкой **'Z6+N3r8cI0AfliSen1oDySwSnEDPMmy/'**, и если они совпадают - доступ к серверу разрешается.

Дело за малым - расшифровать данные, зашифрованные в этой строке! 

Благо, для нашего удобства у нас в **ДЛЛ** даже есть функция-декриптор **sub_41ABF0**, которую мы при желании можем вызвать. 

Хотя, безусловно, мы можем использовать и другие инструменты для расшифровки **DES**.

Так или иначе, но мы получаем недостающую часть пароля, и, добавляя в его начало **RDG{**, получаем сам пароль, **который** по совместительству **является** и **флагом**.


# Flag

RDG{D0Y0urBestAndGetTheFlag}